package com.uwlaser.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.uwlaser.base.CommonCascader;
import com.uwlaser.base.PageInfo;
import com.uwlaser.base.QueryHelpMybatisPlus;
import com.uwlaser.base.impl.CommonServiceImpl;
import com.uwlaser.domain.*;
import com.uwlaser.service.SpcAbnormalRuleService;
import com.uwlaser.service.SpcDataCourseParamService;
import com.uwlaser.service.SpcMainService;
import com.uwlaser.service.dto.*;
import com.uwlaser.service.mapper.*;
import com.uwlaser.utils.ConvertUtil;
import com.uwlaser.utils.PageUtil;
import com.uwlaser.utils.enums.DictValueEnum;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author mx
 * @date 2022-08-19
 */
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = SpcMainService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SpcMainServiceImpl extends CommonServiceImpl<SpcMainMapper, SpcMain> implements SpcMainService {

    // private final RedisUtils redisUtils;
    private final SpcMainMapper spcMainMapper;

    private final FactoryModelMapper factoryModelMapper;

    private final DeviceMainMapper deviceMainMapper;

    private final DataCourseParamMapper dataCourseParamMapper;

    private final SpcAbnormalRuleService spcAbnormalRuleService;

    private final SpcDataCourseParamService spcDataCourseParamService;

    private final SpcAbnormalRuleMapper spcAbnormalRuleMapper;

    private final SpcDataCourseParamMapper spcDataCourseParamMapper;

    /**
     * spc常量
     */
/*
    private final static List<Double> A2 = new ArrayList<>(Arrays.asList(1.880, 1.023, 0.729, 0.577, 0.483, 0.419, 0.373, 0.337, 0.308, 0.285, 0.266, 0.249, 0.235, 0.223, 0.212, 0.203, 0.194, 0.187, 0.180, 0.173, 0.167, 0.162, 0.157, 0.153));

    private final static List<Double> D2 = new ArrayList<>(Arrays.asList(1.128, 1.693, 2.059, 2.326, 2.543, 2.704, 2.847, 2.970, 3.078, 3.173, 3.258, 3.336, 3.407, 3.472, 3.532, 3.588, 3.640, 3.689, 3.735, 3.778, 3.819, 3.858, 3.895, 3.931));

    private final static List<Double> D3 = new ArrayList<>(Arrays.asList(0.000, 0.000, 0.000, 0.000, 0.000, 0.076, 0.136, 0.184, 0.223, 0.256, 0.283, 0.307, 0.328, 0.347, 0.363, 0.378, 0.391, 0.403, 0.415, 0.425, 0.434, 0.443, 0.451, 0.459));

    private final static List<Double> D4 = new ArrayList<>(Arrays.asList(3.267, 2.571, 2.282, 2.114, 2.004, 1.924, 1.864, 1.816, 1.777, 1.744, 1.717, 1.693, 1.672, 1.653, 1.637, 1.622, 1.608, 1.597, 1.585, 1.575, 1.566, 1.557, 1.548, 1.541));

    private final static List<Double> A3 = new ArrayList<>(Arrays.asList(2.659, 1.954, 1.628, 1.427, 1.287, 1.182, 1.099, 1.032, 0.975, 0.927, 0.886, 0.850, 0.817, 0.789, 0.763, 0.739, 0.718, 0.698, 0.680, 0.663, 0.647, 0.633, 0.619, 0.606));

    private final static List<Double> C4 = new ArrayList<>(Arrays.asList(0.7979, 0.8862, 0.9213, 0.9400, 0.9515, 0.9594, 0.9650, 0.9693, 0.9727, 0.9754, 0.9776, 0.9794, 0.9810, 0.9823, 0.9835, 0.9845, 0.9854, 0.9862, 0.9869, 0.9876, 0.9882, 0.9887, 0.9892, 0.9896));

    private final static List<Double> B3 = new ArrayList<>(Arrays.asList(0.000, 0.000, 0.000, 0.000, 0.030, 0.118, 0.185, 0.239, 0.284, 0.321, 0.354, 0.382, 0.406, 0.428, 0.448, 0.446, 0.482, 0.497, 0.510, 0.523, 0.534, 0.545, 0.555, 0.565));

    private final static List<Double> B4 = new ArrayList<>(Arrays.asList(3.276, 2.568, 2.266, 2.089, 1.970, 1.882, 1.815, 1.761, 1.716, 1.679, 1.640, 1.618, 1.594, 1.572, 1.552, 1.534, 1.518, 1.503, 1.490, 1.477, 1.466, 1.455, 1.445, 1.435));
*/

    private final static DecimalFormat decimalFormat = new DecimalFormat("0.000");


    @Override
    public PageInfo<SpcMainDto> queryAll(SpcMainQueryParam query, Pageable pageable) {
        IPage<SpcMain> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<SpcMain> page = spcMainMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        return ConvertUtil.convertPage(page, SpcMainDto.class);
    }

    @Override
    public List<SpcMainDto> queryAll(SpcMainQueryParam query) {
        return ConvertUtil.convertList(spcMainMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), SpcMainDto.class);
    }

    @Override
    public SpcMain getById(Integer id) {
        return spcMainMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public SpcMainDto findById(Integer id) {
        return ConvertUtil.convert(getById(id), SpcMainDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SpcMainDto resources) {
        SpcMain entity = ConvertUtil.convert(resources, SpcMain.class);
        //新增主表数据
        int insert = spcMainMapper.insert(entity);
        //获取异常信息
        List<SpcAbnormalRule> spcAbnormalRules = resources.getSpcAbnormalRules();
        if (!CollectionUtils.isEmpty(spcAbnormalRules)) {
            spcAbnormalRules.forEach(f -> {
                f.setSpcMainId(entity.getId());
            });
            spcAbnormalRuleService.saveBatch(spcAbnormalRules);
        }
        //获取测试数据
        List<SpcDataCourseParamDto> spcDataCourseParams = resources.getSpcDataCourseParams();
        if (!CollectionUtils.isEmpty(spcDataCourseParams)) {
            spcDataCourseParams.forEach(f -> {
                f.setCpId(f.getId());
                f.setSpcMainId(entity.getId());
                f.setId(null);
            });
            List<SpcDataCourseParam> spcDataCourseParams1 = ConvertUtil.convertList(spcDataCourseParams, SpcDataCourseParam.class);
            spcDataCourseParamService.saveBatch(spcDataCourseParams1);
        }
        return insert;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(SpcMainDto resources) {
        SpcMain entity = ConvertUtil.convert(resources, SpcMain.class);
        int ret = spcMainMapper.updateById(entity);
        //删除异常表
        SpcDataCourseParam spcDataCourseParam = new SpcDataCourseParam();
        spcDataCourseParam.setSpcMainId(resources.getId());
        spcDataCourseParamMapper.delete(new QueryWrapper<>(spcDataCourseParam));
        //删除测试表
        SpcAbnormalRule spcAbnormalRule = new SpcAbnormalRule();
        spcAbnormalRule.setSpcMainId(resources.getId());
        spcAbnormalRuleMapper.delete(new QueryWrapper<>(spcAbnormalRule));
        //新增异常表
        //获取异常信息
        List<SpcAbnormalRule> spcAbnormalRules = resources.getSpcAbnormalRules();
        if (!CollectionUtils.isEmpty(spcAbnormalRules)) {
            spcAbnormalRules.forEach(f -> {
                f.setSpcMainId(entity.getId());
            });
            spcAbnormalRuleService.saveBatch(spcAbnormalRules);
        }
        //新增测试表
        //获取测试数据
        List<SpcDataCourseParamDto> spcDataCourseParams = resources.getSpcDataCourseParams();
        if (!CollectionUtils.isEmpty(spcDataCourseParams)) {
            spcDataCourseParams.forEach(f -> {
                f.setCpId(f.getId());
                f.setSpcMainId(entity.getId());
                f.setId(null);
            });
            List<SpcDataCourseParam> spcDataCourseParams1 = ConvertUtil.convertList(spcDataCourseParams, SpcDataCourseParam.class);
            spcDataCourseParamService.saveBatch(spcDataCourseParams1);
        }
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<Integer> ids) {
        // delCaches(ids);
        return spcMainMapper.deleteBatchIds(ids);
    }

    @Override
    public List<CommonCascader> getEquipment() {
        //级联列表
        List<CommonCascader> list = new ArrayList<>();
        //获取所有类型
        List<FactoryModel> factoryModels1 = factoryModelMapper.selectList(null);
        //获取所有设备信息
        List<DeviceMain> deviceMains = deviceMainMapper.selectList(null);
        //存在数据
        if (!CollectionUtils.isEmpty(factoryModels1)) {
            Map<Integer, List<FactoryModel>> collect1 = factoryModels1.stream().collect(Collectors.groupingBy(e -> e.getPid()));
            //获取产线数据
            List<FactoryModel> collect = factoryModels1.stream().filter(f -> f.getModelType()
                    .equals(DictValueEnum.MODEL_TYPE_LINE.getValue())).collect(Collectors.toList());
            //存在数据开始封装数据
            if (!CollectionUtils.isEmpty(collect)) {
                for (FactoryModel model : collect) {
                    CommonCascader commonCascader = new CommonCascader();
                    commonCascader.setValue(model.getModelCode());
                    commonCascader.setLabel(model.getModelName());
                    setData(commonCascader, collect1, model.getId(), deviceMains);
                    list.add(commonCascader);
                }
            }
        }
        return list;
    }

    @Override
    public List<TestItemDao> getTestItem(String equipmentCode) {
        return spcMainMapper.getTestItem(equipmentCode);
    }

    @Override
    public List<DeviceMain> getDevicename(String productCode) {
        return spcMainMapper.getDevicename(productCode);
    }

    @Override
    public List<DataCourseParam> getDatalist(DataCourseParam param) {
        return dataCourseParamMapper.selectList(new QueryWrapper<>(param));
    }

    @Override
    public SpcMainDto getRedact(Integer id) {
        SpcMainDto spcMainDto = new SpcMainDto();
        //获取测试的数据
        SpcDataCourseParam spcDataCourseParam = new SpcDataCourseParam();
        spcDataCourseParam.setSpcMainId(id);
        List<SpcDataCourseParam> spcDataCourseParams = spcDataCourseParamMapper.selectList(new QueryWrapper<>(spcDataCourseParam));
        if (!CollectionUtils.isEmpty(spcDataCourseParams)) {
            spcDataCourseParams.forEach(f -> {
                f.setId(Long.parseLong(f.getCpId()));
            });
        }
        List<SpcDataCourseParamDto> spcDataCourseParams1 = ConvertUtil.convertList(spcDataCourseParams, SpcDataCourseParamDto.class);
        spcMainDto.setSpcDataCourseParams(spcDataCourseParams1);
        //获取判断规则
        SpcAbnormalRule spcAbnormalRule = new SpcAbnormalRule();
        spcAbnormalRule.setSpcMainId(id);
        List<SpcAbnormalRule> spcAbnormalRules = spcAbnormalRuleMapper.selectList(new QueryWrapper<>(spcAbnormalRule));
        spcMainDto.setSpcAbnormalRules(spcAbnormalRules);
        return spcMainDto;
    }

    @Override
    public Map<String, Object> getSpc(Integer id) {
        //获取spc主表信息
        SpcMain spcMain = spcMainMapper.selectById(id);
        //获取测试数据
        SpcDataCourseParam spcDataCourseParam = new SpcDataCourseParam();
        spcDataCourseParam.setSpcMainId(id);
        List<SpcDataCourseParam> spcDataCourseParams = new ArrayList<>();
        //查看是否自动获取数据
        if (spcMain.getAutomatic()) {
            List<DataCourseParam> dataCourseParams = dataCourseParamMapper.selectList(new LambdaQueryWrapper<DataCourseParam>()
                    .eq(DataCourseParam::getProductCode, spcMain.getProductCode()).eq(DataCourseParam::getDeviceCode, spcMain.getEquipmentCode())
                    .eq(DataCourseParam::getParamCode, spcMain.getTestItem()).orderByDesc(DataCourseParam::getCreateTime).last("limit " + spcMain.getQuantity()));
            if (!CollectionUtils.isEmpty(dataCourseParams)) {
                spcDataCourseParams.addAll(ConvertUtil.convertList(dataCourseParams, SpcDataCourseParam.class));
            }
        } else {
            spcDataCourseParams.addAll(spcDataCourseParamMapper.selectList(new QueryWrapper<>(spcDataCourseParam)));
        }

        //获取异常数据
        SpcAbnormalRule spcAbnormalRule = new SpcAbnormalRule();
        spcAbnormalRule.setSpcMainId(id);
        List<SpcAbnormalRule> spcAbnormalRules = spcAbnormalRuleMapper.selectList(new QueryWrapper<>(spcAbnormalRule));

        if ("0".equals(spcMain.getGraphType())) {
            //xr图
            return getXr(spcMain, spcDataCourseParams, spcAbnormalRules);
        } else if ("1".equals(spcMain.getGraphType())) {
            //xs图
            return getXs(spcMain, spcDataCourseParams, spcAbnormalRules);
        } else {
            return null;
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(Integer id) {
        Set<Integer> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }


    /**
     * 递归封装数据
     */
    public void setData(CommonCascader commonCascader, Map<Integer, List<FactoryModel>> collect, Integer pid, List<DeviceMain> deviceMains) {
        List<FactoryModel> factoryModels = collect.get(pid);
        if (CollectionUtils.isEmpty(factoryModels)) {
            return;
        }
        //拼装数据
        List<CommonCascader> list = new ArrayList<>();
        //拼装数据
        factoryModels.forEach(f -> {
            CommonCascader c = new CommonCascader();
            c.setPid(f.getPid().toString());
            c.setValue(f.getModelCode());
            c.setLabel(f.getModelName());
            c.setModelType(f.getModelType());
            c.setId(f.getId());
            list.add(c);
        });
        commonCascader.setChildren(list);
        for (CommonCascader cascader : commonCascader.getChildren()) {
            if (cascader.getModelType().equals(DictValueEnum.MODEL_TYPE_STATION.getValue())) {
                setEquipment(deviceMains, cascader);
            }
            setData(cascader, collect, cascader.getId(), deviceMains);
        }

    }

    /**
     * 拼装设备
     */
    public void setEquipment(List<DeviceMain> deviceMains, CommonCascader cascader) {
        if (!CollectionUtils.isEmpty(deviceMains)) {
            List<CommonCascader> list = new ArrayList<>();
            List<DeviceMain> collect = deviceMains.stream().filter(
                    f -> f.getStationCode().equals(cascader.getValue())).collect(Collectors.toList());
            collect.forEach(f -> {
                CommonCascader c = new CommonCascader();
                c.setLabel(f.getDeviceName());
                c.setValue(f.getDeviceCode());
                list.add(c);
            });
            cascader.setChildren(list);
        }
    }

    /**
     * @param id
     * @param factoryModels1
     */
    public void filtrationWorkshop(Integer id, List<FactoryModel> factoryModels1, List<FactoryModel> list) {
        List<FactoryModel> collect = factoryModels1.stream().filter(f -> f.getId().equals(id)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect) || Integer.parseInt(collect.get(0).getModelType()) < 3) {
            return;
        }
        list.addAll(collect);
        filtrationWorkshop(collect.get(0).getPid(), factoryModels1, list);
    }


    /**
     * X-Bar R 图
     */
    public Map<String, Object> getXr(SpcMain spcMain, List<SpcDataCourseParam> spcDataCourseParams, List<SpcAbnormalRule> spcAbnormalRules) {
        Map<String, Object> mapPicture = new HashMap<>();
        //样本容量
        Integer capacity = spcMain.getCapacity();
        //拼装表头
        mapPicture.put("header", getHeader(capacity));
        Map<Integer, List<SpcDataCourseParam>> map = new HashMap<>();
        List<Map<String, Object>> data = new ArrayList<>();
        List<SpcParticulars> list = new ArrayList<>();
        //图数据
        List<SpcDao> spcDaos = new ArrayList<>();
        //平均值
        List<Double> means = new ArrayList<>();
        //合格率
        List<Double> percents = new ArrayList<>();
        //整体数据
        List<Double> collect2 = spcDataCourseParams.stream().map(SpcDataCourseParam::getParamValue).collect(Collectors.toList());
        //整体数据总和
        double sum2 = spcDataCourseParams.stream().mapToDouble(SpcDataCourseParam::getParamValue).sum();
        //所有数据
        List<Double> allData = collect2;
        //整体标准差 =
        double entiretyStandard = getStandardValue(collect2, (sum2 / collect2.size()), collect2.size());
        //数据分组
        int n = 0;
        for (int i = 0; i < spcDataCourseParams.size(); i += capacity) {
            List<SpcDataCourseParam> collect = spcDataCourseParams.stream().skip(i).limit(capacity).collect(Collectors.toList());
            SpcParticulars spcParticulars = new SpcParticulars();
            //获取参数值
            List<Double> collect1 = collect.stream().map(SpcDataCourseParam::getParamValue).collect(Collectors.toList());
            //获取合格数量
            List<SpcDataCourseParam> collect3 = collect.stream().filter(f -> "1".equals(f.getParamResult())).collect(Collectors.toList());
            int percent = CollectionUtils.isEmpty(collect3) ? 0 : collect3.size();
            //计算合格率
            percents.add(percent/(double)collect.size() * 100);
            double sum = collect.stream().mapToDouble(SpcDataCourseParam::getParamValue).sum();

            //平均值
            spcParticulars.setMean(sum / capacity);
            //最大值
            spcParticulars.setMax(collect1.stream().max(Comparator.comparing(x -> x)).orElse(null));
            //最小值
            spcParticulars.setMin(collect1.stream().min(Comparator.comparing(x -> x)).orElse(null));
            //极差值
            spcParticulars.setPoorValue(spcParticulars.getMax() - spcParticulars.getMin());
            //组装数据
            data.add(getData(collect1, spcParticulars.getMean(), spcParticulars.getPoorValue(), spcParticulars.getMax(), spcParticulars.getMin()));
            list.add(spcParticulars);
            map.put(++n, collect);
        }

        if (!CollectionUtils.isEmpty(list)) {

            //获取平均数总值
            double sum = list.stream().mapToDouble(SpcParticulars::getMean).sum();
            //异常判断规则
            List<Double> collect3 = list.stream().map(SpcParticulars::getMean).collect(Collectors.toList());
            List<BigDecimal> collect4 = collect3.stream().map(BigDecimal::new).collect(Collectors.toList());
            means.addAll(collect3);
            //获取所有极差总值
            double sum1 = list.stream().mapToDouble(SpcParticulars::getPoorValue).sum();
            //平均值
            double average = sum / list.size();
            //极差平均值
            double rangeAverage = sum1 / list.size();
            //xb图
            SpcDao xb = new SpcDao();
            xb.setName("x-b(均值控制图)");
            //UCL 上控制限 所有数据平均值 + A2 * 所有极差平均值
            double ucl = average + SpcMean.A2.get(capacity - 2) * rangeAverage;
            xb.setUcl(decimalFormat.format(ucl));
            //CL 中心限 所有数据平均值
            xb.setCt(decimalFormat.format(average));
            //LCL 下控制限 所有数据平均值 - A2*所有极差平均值
            double lcl = average - SpcMean.A2.get(capacity - 2) * rangeAverage;
            if (!CollectionUtils.isEmpty(spcAbnormalRules)){
                List<Integer> integers = abnormalJudgment(collect4, spcAbnormalRules,
                        BigDecimal.valueOf(average), BigDecimal.valueOf(entiretyStandard), BigDecimal.valueOf(ucl), BigDecimal.valueOf(lcl));
                //修改数据为异常
                xb.setAbnormals(integers);
                updateAbnormal(data, integers);
            }
            xb.setLcl(decimalFormat.format(lcl));
            //x轴
            xb.setXAxis(map.keySet());
            //data
            List<Double> collect = list.stream().map(e -> {
                BigDecimal b = new BigDecimal(e.getMean());
                return b.setScale(3, BigDecimal.ROUND_UP).doubleValue();
            }).collect(Collectors.toList());
            xb.setData(collect);
            //获取最大值
            Double aDouble = collect.stream().max(Comparator.comparing(x -> x)).orElse(null);
            //获取最小值
            Double aDouble1 = collect.stream().min(Comparator.comparing(x -> x)).orElse(null);
            //设置最大值
            xb.setMax(decimalFormat.format(Math.max(aDouble, ucl)));
            //设置最小值
            xb.setMin(decimalFormat.format(Math.min(aDouble1, lcl)));
            //设置图类
            xb.setTilemap("x-b");
            //组内标准差 = 平均极差 / 标准差系数d2
            double intraStandard = rangeAverage / SpcMean.D2.get(capacity - 2);

            //xr图
            SpcDao xr = new SpcDao();
            xr.setName("x-r(极差控制图)");
            //UCL D4 * 所有极差平均值
            ucl = SpcMean.D4.get(capacity - 2) * rangeAverage;
            xr.setUcl(decimalFormat.format(ucl));
            //CL 所有极差平均值
            xr.setCt(decimalFormat.format(rangeAverage));
            //LCL Max(0,D3*所有极差平均值)
            lcl = Math.max(0.0, SpcMean.D3.get(capacity - 2) * rangeAverage);
            xr.setLcl(decimalFormat.format(lcl));
            //x轴
            xr.setXAxis(map.keySet());
            //data
            List<Double> collect1 = list.stream().map(e -> {
                BigDecimal b = new BigDecimal(e.getPoorValue());
                return b.setScale(3, BigDecimal.ROUND_UP).doubleValue();
            }).collect(Collectors.toList());
            xr.setData(collect1);
            //获取最大值
            Double aDouble2 = collect1.stream().max(Comparator.comparing(x -> x)).orElse(null);
            //获取最小值
            Double aDouble3 = collect1.stream().min(Comparator.comparing(x -> x)).orElse(null);
            //设置最大值
            xr.setMax(decimalFormat.format(Math.max(aDouble2, ucl)));
            //设置最小值
            xr.setMin(decimalFormat.format(Math.min(aDouble3, lcl)));
            //设置图类
            xr.setTilemap("x-r");
            //添加数据
            spcDaos.add(xb);
            spcDaos.add(xr);

            //上限
            double specificationUpperLimit = Double.valueOf(spcMain.getSpecificationUpperLimit());
            //下限
            double specificationFloor = Double.valueOf(spcMain.getSpecificationFloor());

            if (specificationUpperLimit == 0 && specificationFloor == 0) {
                mapPicture.put("cp", 0);
                mapPicture.put("cpl", 0);
                mapPicture.put("cpu", 0);
                mapPicture.put("cpk", 0);
                mapPicture.put("pp", 0);
                mapPicture.put("ppu", 0);
                mapPicture.put("ppl", 0);
                mapPicture.put("ppk", 0);
            } else {
                //CP (过程能力指数): (UCL - LCL) / (6*组内标准差)
                double cp = (specificationUpperLimit - specificationFloor) / (6 * intraStandard);
                //CPL(下限过程能力指数):(所有数据平均值 - LCL) / (3 * 组内标准差)
                double cpl = (average - specificationFloor) / (3 * intraStandard);
                //CPU (上限过程能力指数):(UCL  - 所有数据平均值) /  (3 * 组内标准差)
                double cpu = (specificationUpperLimit - average) / (3 * intraStandard);
                //CPK (修改的过程能力指数):(上限-平均值,平均值-下限)取小 / (3*组内标准差)
                double cpk = Math.min(specificationUpperLimit - average, average - specificationFloor) / (3 * intraStandard);
                //PP (过程性能指数):(上限 - 下限) / (6* 整体标准差)
                double pp = (specificationUpperLimit - specificationFloor) / (6 * entiretyStandard);
                //PPu (上限过程性能指数):(上限 - 所有数据平均值) / (3 * 整体标准差)
                double ppu = (specificationUpperLimit - average) / (3 * entiretyStandard);
                //PPl (下限过程性能指数):(所有数据平均值 - 下限) /  (3 * 整体标准差)
                double ppl = (average - specificationFloor) / (3 * entiretyStandard);
                //PPk (修正的过程性能指数):(上限-平均值,平均值-下限)取小 / (3*整体标准差)
                double ppk = Math.min(specificationUpperLimit - average, average - specificationFloor) / 3 * entiretyStandard;
                mapPicture.put("cp", decimalFormat.format(cp));
                mapPicture.put("cpl", decimalFormat.format(cpl));
                mapPicture.put("cpu", decimalFormat.format(cpu));
                mapPicture.put("cpk", decimalFormat.format(cpk));
                mapPicture.put("pp", decimalFormat.format(pp));
                mapPicture.put("ppu", decimalFormat.format(ppu));
                mapPicture.put("ppl", decimalFormat.format(ppl));
                mapPicture.put("ppk", decimalFormat.format(ppk));
            }
        }
        mapPicture.put("data", data);
        mapPicture.put("picture", spcDaos);
        mapPicture.put("means",means);
        mapPicture.put("percents",percents);
        mapPicture.put("allData",allData);
        return mapPicture;
    }

    /**
     * X-Bar Sigma
     */
    public Map<String, Object> getXs(SpcMain spcMain, List<SpcDataCourseParam> spcDataCourseParams, List<SpcAbnormalRule> spcAbnormalRules) {
        Map<String, Object> mapPicture = new HashMap<>();
        //样本容量
        Integer capacity = spcMain.getCapacity();
        Map<Integer, List<SpcDataCourseParam>> map = new HashMap<>();
        List<SpcParticularsDto> list = new ArrayList<>();
        //拼装表头
        mapPicture.put("header", getHeader(capacity));
        //整体数据
        List<Double> collect2 = spcDataCourseParams.stream().map(SpcDataCourseParam::getParamValue).collect(Collectors.toList());
        //整体数据总和
        double sum3 = spcDataCourseParams.stream().mapToDouble(SpcDataCourseParam::getParamValue).sum();
        //整体标准差 =
        double entiretyStandard = getStandardValue(collect2, (sum3 / collect2.size()), collect2.size());
        List<Map<String, Object>> data = new ArrayList<>();
        //图数据
        List<SpcDao> spcDaos = new ArrayList<>();
        //平均值
        List<Double> means = new ArrayList<>();
        //合格率
        List<Double> percents = new ArrayList<>();
        //所有数据
        List<Double> allData = collect2;

        //数据分组
        int n = 0;
        for (int i = 0; i < spcDataCourseParams.size(); i += capacity) {
            List<SpcDataCourseParam> collect = spcDataCourseParams.stream().skip(i).limit(capacity).collect(Collectors.toList());
            SpcParticularsDto spcParticulars = new SpcParticularsDto();
            //获取参数值
            List<Double> collect1 = collect.stream().map(SpcDataCourseParam::getParamValue).collect(Collectors.toList());
            //获取合格数量
            List<SpcDataCourseParam> collect3 = collect.stream().filter(f -> "1".equals(f.getParamResult())).collect(Collectors.toList());
            int percent = CollectionUtils.isEmpty(collect3) ? 0 : collect3.size();
            //计算合格率
            percents.add(percent/(double)collect.size() * 100);
            double sum = collect.stream().mapToDouble(SpcDataCourseParam::getParamValue).sum();
            //平均值
            spcParticulars.setMean(sum / capacity);
            //最大值
            spcParticulars.setMax(collect1.stream().max(Comparator.comparing(x -> x)).orElse(null));
            //最小值
            spcParticulars.setMin(collect1.stream().min(Comparator.comparing(x -> x)).orElse(null));
            //极差值
            spcParticulars.setPoorValue(spcParticulars.getMax() - spcParticulars.getMin());
            //标准差
            spcParticulars.setStandardValue(getStandardValue(collect1, spcParticulars.getMean(), capacity));
            //组装数据
            data.add(getData(collect1, spcParticulars.getMean(), spcParticulars.getPoorValue(), spcParticulars.getMax(), spcParticulars.getMin()));
            list.add(spcParticulars);
            map.put(++n, collect);
        }

        if (!CollectionUtils.isEmpty(list)) {
            //异常判断规则
            List<Double> collect3 = list.stream().map(SpcParticularsDto::getMean).collect(Collectors.toList());
            means.addAll(collect3);
            List<BigDecimal> collect4 = collect3.stream().map(BigDecimal::new).collect(Collectors.toList());
            //获取所有极差总值
            double sum1 = list.stream().mapToDouble(SpcParticularsDto::getPoorValue).sum();
            //极差平均值
            double rangeAverage = sum1 / list.size();
            //获取平均数总值
            double sum = list.stream().mapToDouble(SpcParticularsDto::getMean).sum();
            // 获取所有标准差种值
            double sum2 = list.stream().mapToDouble(SpcParticularsDto::getStandardValue).sum();
            //平均值
            double average = sum / list.size();
            //标准差平均值
            double standardAverage = sum2 / list.size();
            //xb图
            SpcDao xb = new SpcDao();
            xb.setName("x-b(均值控制图)");
            //UCL 上控制限 所有数据平均值 + A3 * 所有标准差平均值
            double ucl = average + SpcMean.A3.get(capacity - 2) * standardAverage;
            xb.setUcl(decimalFormat.format(ucl));
            //CL 中心限 所有数据平均值
            xb.setCt(decimalFormat.format(average));
            //LCL 下控制限 所有数据平均值 - A3*所有标准差平均值
            double lcl = average - SpcMean.A3.get(capacity - 2) * standardAverage;
            if (!CollectionUtils.isEmpty(spcAbnormalRules)){
                List<Integer> integers = abnormalJudgment(collect4, spcAbnormalRules, BigDecimal.valueOf(average), BigDecimal.valueOf(entiretyStandard)
                        , BigDecimal.valueOf(ucl), BigDecimal.valueOf(lcl));
                //修改数据为异常
                xb.setAbnormals(integers);
                updateAbnormal(data, integers);
            }
            xb.setLcl(decimalFormat.format(lcl));
            //x轴
            xb.setXAxis(map.keySet());
            //data
            List<Double> collect = list.stream().map(e -> {
                BigDecimal b = new BigDecimal(e.getMean());
                return b.setScale(3, BigDecimal.ROUND_UP).doubleValue();
            }).collect(Collectors.toList());
            xb.setData(collect);
            //获取最大值
            Double aDouble = collect.stream().max(Comparator.comparing(x -> x)).orElse(null);
            //获取最小值
            Double aDouble1 = collect.stream().min(Comparator.comparing(x -> x)).orElse(null);
            //设置最大值
            xb.setMax(decimalFormat.format(Math.max(aDouble, ucl)));
            //设置最小值
            xb.setMin(decimalFormat.format(Math.min(aDouble1, lcl)));
            //设置图类
            xb.setTilemap("x-b");

            //组内标准差 = 平均极差 / 标准差系数d2
            double intraStandard = rangeAverage / SpcMean.D2.get(capacity - 2);

            //xr图
            SpcDao xr = new SpcDao();
            xr.setName("x-s(标准差控制图)");
            //UCL B4 * 所有标准差平均值
            ucl = SpcMean.B4.get(capacity - 2) * standardAverage;
            xr.setUcl(decimalFormat.format(ucl));
            //CL 所有标准差平均值
            xr.setCt(decimalFormat.format(standardAverage));
            //LCL Max(0,B3*所有标准差平均值)
            lcl = Math.max(0.0, SpcMean.B3.get(capacity - 2) * standardAverage);
            xr.setLcl(decimalFormat.format(lcl));
            //x轴
            xr.setXAxis(map.keySet());
            //data
            List<Double> collect1 = list.stream().map(e -> {
                BigDecimal b = new BigDecimal(e.getStandardValue());
                return b.setScale(3, BigDecimal.ROUND_UP).doubleValue();
            }).collect(Collectors.toList());
            xr.setData(collect1);
            //获取最大值
            Double aDouble2 = collect1.stream().max(Comparator.comparing(x -> x)).orElse(null);
            //获取最小值
            Double aDouble3 = collect1.stream().min(Comparator.comparing(x -> x)).orElse(null);
            //设置最大值
            xr.setMax(decimalFormat.format(Math.max(aDouble2, ucl)));
            //设置最小值
            xr.setMin(decimalFormat.format(Math.min(aDouble3, lcl)));
            //设置图类
            xr.setTilemap("x-s");
            //添加数据
            spcDaos.add(xb);
            spcDaos.add(xr);
            //上限
            double specificationUpperLimit = Double.valueOf(spcMain.getSpecificationUpperLimit());
            //下限
            double specificationFloor = Double.valueOf(spcMain.getSpecificationFloor());
            if (specificationUpperLimit == 0 && specificationFloor == 0) {
                mapPicture.put("cp", 0);
                mapPicture.put("cpl", 0);
                mapPicture.put("cpu", 0);
                mapPicture.put("cpk", 0);
                mapPicture.put("pp", 0);
                mapPicture.put("ppu", 0);
                mapPicture.put("ppl", 0);
                mapPicture.put("ppk", 0);
            } else {
                //CP (过程能力指数): (UCL - LCL) / (6*组内标准差)
                double cp = (specificationUpperLimit - specificationFloor) / (6 * intraStandard);
                //CPL(下限过程能力指数):(所有数据平均值 - LCL) / (3 * 组内标准差)
                double cpl = (average - specificationFloor) / (3 * intraStandard);
                //CPU (上限过程能力指数):(UCL  - 所有数据平均值) /  (3 * 组内标准差)
                double cpu = (specificationUpperLimit - average) / (3 * intraStandard);
                //CPK (修改的过程能力指数):(上限-平均值,平均值-下限)取小 / (3*组内标准差)
                double cpk = Math.min(specificationUpperLimit - average, average - specificationFloor) / (3 * intraStandard);
                //PP (过程性能指数):(上限 - 下限) / (6* 整体标准差)
                double pp = (specificationUpperLimit - specificationFloor) / (6 * entiretyStandard);
                //PPu (上限过程性能指数):(上限 - 所有数据平均值) / (3 * 整体标准差)
                double ppu = (specificationUpperLimit - average) / (3 * entiretyStandard);
                //PPl (下限过程性能指数):(所有数据平均值 - 下限) /  (3 * 整体标准差)
                double ppl = (average - specificationFloor) / (3 * entiretyStandard);
                //PPk (修正的过程性能指数):(上限-平均值,平均值-下限)取小 / (3*整体标准差)
                double ppk = Math.min(specificationUpperLimit - average, average - specificationFloor) / 3 * entiretyStandard;
                mapPicture.put("cp", decimalFormat.format(cp));
                mapPicture.put("cpl", decimalFormat.format(cpl));
                mapPicture.put("cpu", decimalFormat.format(cpu));
                mapPicture.put("cpk", decimalFormat.format(cpk));
                mapPicture.put("pp", decimalFormat.format(pp));
                mapPicture.put("ppu", decimalFormat.format(ppu));
                mapPicture.put("ppl", decimalFormat.format(ppl));
                mapPicture.put("ppk", decimalFormat.format(ppk));
            }
        }
        mapPicture.put("picture", spcDaos);
        mapPicture.put("data", data);
        mapPicture.put("means",means);
        mapPicture.put("percents",percents);
        mapPicture.put("allData",allData);
        return mapPicture;
    }


    /**
     * 计算标准差
     *
     * @param collect  参数
     * @param mean     平均值
     * @param capacity 个数
     * @return
     */
    public Double getStandardValue(List<Double> collect, Double mean, Integer capacity) {
        double num = 0.0;
        for (Double aDouble : collect) {
            num += Math.pow((aDouble - mean), 2);
        }
        return Math.sqrt(num / (capacity - 1));
    }

    /**
     * 拼装表头
     */
    public List<HeaderDao> getHeader(Integer capacity) {
        List<HeaderDao> list = new ArrayList<>();
        for (Integer i = 0; i < capacity; i++) {
            HeaderDao headerDao = new HeaderDao();
            headerDao.setProp("parameter" + (i + 1));
            headerDao.setLabel("参数" + (i + 1));
            list.add(headerDao);
        }
        HeaderDao headerDao = new HeaderDao();
       /* headerDao.setProp("state");
        headerDao.setLabel("状态");
        list.add(headerDao);*/
        headerDao = new HeaderDao();
        headerDao.setProp("mean");
        headerDao.setLabel("平均值");
        list.add(headerDao);
        headerDao = new HeaderDao();
        headerDao.setProp("poorValue");
        headerDao.setLabel("极差值");
        list.add(headerDao);
        headerDao = new HeaderDao();
        headerDao.setProp("max");
        headerDao.setLabel("最大值");
        list.add(headerDao);
        headerDao = new HeaderDao();
        headerDao.setProp("min");
        headerDao.setLabel("最小值");
        list.add(headerDao);
        return list;
    }

    /**
     * 组装数据
     */
    public Map<String, Object> getData(List<Double> collect, Double mean, Double poorValue, Double max, Double min) {
        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < collect.size(); i++) {
            map.put("parameter" + (i + 1), collect.get(i));
        }
        map.put("state", "正常");
        map.put("mean", decimalFormat.format(mean));
        map.put("poorValue", decimalFormat.format(poorValue));
        map.put("max", max);
        map.put("min", min);
        return map;
    }


    /**
     * 获取判异规则
     *
     * @param datas            数据
     * @param spcAbnormalRules 判异
     * @param mean             平均值
     * @param entiretyStandard 标准差
     * @return
     */
    public List<Integer> abnormalJudgment(List<BigDecimal> datas, List<SpcAbnormalRule> spcAbnormalRules, BigDecimal mean, BigDecimal entiretyStandard,
                                          BigDecimal ucl, BigDecimal lcl) {
        List<Integer> abnormalDataIndexs = new ArrayList<>();
        if (CollectionUtils.isEmpty(spcAbnormalRules)) {
            return null;
        }
        // 数据计算容器
        List<Integer> r1 = new ArrayList<>();
        int twoDirection = 1;  // 1：中心线上方。-1：中心线下方 （标准2）
        List<Integer> twoAbnormalIndex = new ArrayList<>(); // 累计异常数据下标（标准2）
        int threeDirection = 1;  // 1：上升   -1：下降 （标准3）
        List<Integer> threeAbnormalIndex = new ArrayList<>(); // 累计异常数据下标（标准3）
        int fourDirection = 1;  // 1：上升   -1：下降 （标准4）
        List<Integer> fourAbnormalIndex = new ArrayList<>(); // 累计异常数据下标（标准4）
        List<Integer> sevenAbnormalIndex = new ArrayList<>(); // 累计异常数据下标（标准7）
        List<Integer> eightAbnormalIndex = new ArrayList<>(); // 累计异常数据下标（标准8）

        for (int i = 0; i < datas.size(); i++) {
            BigDecimal data = datas.get(i);
            for (SpcAbnormalRule spcAbnormalRule : spcAbnormalRules) {
                BigDecimal n = BigDecimal.valueOf(spcAbnormalRule.getN() == null ? 0 : spcAbnormalRule.getN());
                BigDecimal m = BigDecimal.valueOf(spcAbnormalRule.getM() == null ? 0 : spcAbnormalRule.getM());
                BigDecimal k = BigDecimal.valueOf(spcAbnormalRule.getK() == null ? 0 : spcAbnormalRule.getK());
                switch (spcAbnormalRule.getCoding()) {
                    case "R0":
                        if (data.compareTo(ucl) > 0 || data.compareTo(lcl) < 0) {
                            abnormalDataIndexs.add(i);
                        }
                        break;
                    case "R1"://[n]个点落在[m]倍sigma区以外
                        if (data.compareTo(mean.add(m.multiply(entiretyStandard))) > 0 || data.compareTo(mean.subtract(m.multiply(entiretyStandard))) < 0) {
                            r1.add(i);
                        }
                        if (r1.size() >= n.intValue()) {
                            abnormalDataIndexs.addAll(r1);
                            r1.clear();
                        }
                        break;
                    case "R2"://连续[n]点落在中心线同一侧
                        if (n.intValue() > 1) {
                            if (i == 0) {
                                twoDirection = data.compareTo(mean) > 0 ? 1 : -1;
                                twoAbnormalIndex.add(i);
                            } else {
                                // 跟上个数据在同一侧，累加
                                if ((data.compareTo(mean) > 0 && twoDirection > 0) || (data.compareTo(mean) < 0 && twoDirection < 0)) {
                                    twoAbnormalIndex.add(i);
                                    if (twoAbnormalIndex.size() == n.intValue()) {  //第一次到达阈值，把前面符合条件的数据都存入警告集合；
                                        abnormalDataIndexs.addAll(twoAbnormalIndex);
                                    } else if (twoAbnormalIndex.size() > n.intValue()) {
                                        abnormalDataIndexs.add(i);
                                    }
                                }
                                // 不符合报警条件，归零重新计算
                                else {
                                    twoDirection = data.compareTo(mean) > 0 ? 1 : -1;
                                    twoAbnormalIndex.clear();
                                    twoAbnormalIndex.add(i);
                                }
                            }
                        }
                        break;
                    case "R3"://连续[n]点递增或递减
                        if (n.intValue() > 1) {
                            if (i < 2) {
                                threeAbnormalIndex.add(i);  // 判断方向至少需要两个点，初始值默认要存两个，从第三个开始判断是否递增递减；
                            } else {
                                // 跟上个数据同个趋势，累加
                                if ((data.compareTo(datas.get(i - 1)) > 0 && threeDirection > 0) || (data.compareTo(datas.get(i - 1)) < 0 && threeDirection < 0)) {
                                    threeAbnormalIndex.add(i);
                                    if (threeAbnormalIndex.size() == n.intValue()) {  //第一次到达阈值，把前面符合条件的数据都存入警告集合；
                                        abnormalDataIndexs.addAll(threeAbnormalIndex);
                                    } else if (threeAbnormalIndex.size() > n.intValue()) {
                                        abnormalDataIndexs.add(i);
                                    }
                                }
                                // 不符合报警条件，归零重新计算
                                else {
                                    threeDirection = data.compareTo(datas.get(i - 1)) > 0 ? 1 : -1;
                                    threeAbnormalIndex.clear();
                                    threeAbnormalIndex.add(i - 1);
                                    threeAbnormalIndex.add(i);
                                }
                            }
                        }
                        break;
                    case "R4":// 连续[n]点中相邻点交替上下
                        if (n.intValue() > 1) {
                            if (i < 2) {
                                fourAbnormalIndex.add(i); // 判断方向至少需要两个点，初始值默认要存两个，从第三个开始判断是否递增递减；
                            } else {
                                // 跟上个数据不同趋势，累加
                                if ((data.compareTo(datas.get(i - 1)) > 0 && fourDirection < 0) || (data.compareTo(datas.get(i - 1)) < 0 && fourDirection > 0)) {
                                    fourDirection = data.compareTo(datas.get(i - 1)) > 0 ? 1 : -1;  // 方向重置
                                    fourAbnormalIndex.add(i);
                                    if (fourAbnormalIndex.size() == n.intValue()) {  //第一次到达阈值，把前面符合条件的数据都存入警告集合；
                                        abnormalDataIndexs.addAll(fourAbnormalIndex);
                                    } else if (fourAbnormalIndex.size() > n.intValue()) {
                                        abnormalDataIndexs.add(i);
                                    }
                                }
                                // 不符合报警条件，归零重新计算
                                else {
                                    fourDirection = data.compareTo(datas.get(i - 1)) > 0 ? 1 : -1;
                                    fourAbnormalIndex.clear();
                                    fourAbnormalIndex.add(i - 1);
                                    fourAbnormalIndex.add(i);
                                }
                            }
                        }
                        break;
                    case "R5"://连续[n]点中有[m]点落在中心线同一测的[k]倍sigma区以外
                        List<Integer> fiveUpAbnormalIndex = new ArrayList<>(); // 中心线上方累计异常数据下标（标准5）
                        List<Integer> fiveDownAbnormalIndex = new ArrayList<>(); // 中心线下方累计异常数据下标（标准5）
                        // 从第K个值开始统计，往前遍历是否有K-1个值符合条件
                        if (i >= m.intValue()) {
                            for (int j = 0; j < n.intValue(); j++) {
                                if (datas.get(i - j).compareTo(mean.add(k.multiply(entiretyStandard))) > 0) {
                                    fiveUpAbnormalIndex.add(i);
                                }
                                if (datas.get(i - j).compareTo(mean.subtract(k.multiply(entiretyStandard))) < 0) {
                                    fiveDownAbnormalIndex.add(i);
                                }
                            }
                            if (fiveUpAbnormalIndex.size() >= m.intValue()) {
                                abnormalDataIndexs.addAll(fiveUpAbnormalIndex);
                            }
                            if (fiveDownAbnormalIndex.size() >= m.intValue()) {
                                abnormalDataIndexs.addAll(fiveDownAbnormalIndex);
                            }
                        }
                        break;
                    case "R6"://连续[n]点中有[m]点落在中心线同一侧的[k]倍sigma区以外
                        List<Integer> sixUpAbnormalIndex = new ArrayList<>(); // 中心线上方累计异常数据下标（标准6）
                        List<Integer> sixDownAbnormalIndex = new ArrayList<>(); // 中心线下方累计异常数据下标（标准6）
                        // 从第K个值开始统计，往前遍历是否有K-1个值符合条件
                        if (i >= m.intValue()) {
                            for (int j = 0; j < n.intValue(); j++) {
                                if (datas.get(i - j).compareTo(mean.add(k.multiply(entiretyStandard))) > 0) {
                                    sixUpAbnormalIndex.add(i);
                                }
                                if (datas.get(i - j).compareTo(mean.subtract(k.multiply(entiretyStandard))) < 0) {
                                    sixDownAbnormalIndex.add(i);
                                }
                            }
                            if (sixUpAbnormalIndex.size() >= m.intValue()) {
                                abnormalDataIndexs.addAll(sixUpAbnormalIndex);
                            }
                            if (sixDownAbnormalIndex.size() >= m.intValue()) {
                                abnormalDataIndexs.addAll(sixDownAbnormalIndex);
                            }
                        }
                        break;
                    case "R7"://连续[n]点落在中心线两侧的[m]倍sigma区内
                        if (data.compareTo(mean.add(m.multiply(entiretyStandard))) < 0 || data.compareTo(mean.subtract(m.multiply(entiretyStandard))) > 0) {
                            sevenAbnormalIndex.add(i);
                            if (sevenAbnormalIndex.size() == n.intValue()) {  //第一次到达阈值，把前面符合条件的数据都存入警告集合；
                                abnormalDataIndexs.addAll(sevenAbnormalIndex);
                            } else if (sevenAbnormalIndex.size() > n.intValue()) {
                                abnormalDataIndexs.add(i);
                            }
                        }
                        // 不符合报警条件，归零重新计算
                        else {
                            sevenAbnormalIndex.clear();
                        }
                        break;
                    case "R8"://连续[n]点落在中心线两侧且无一在[m]倍sigma区内
                        if (data.compareTo(mean.add(m.multiply(entiretyStandard))) > 0 || data.compareTo(mean.subtract(m.multiply(entiretyStandard))) < 0) {
                            eightAbnormalIndex.add(i);
                            if (eightAbnormalIndex.size() == n.intValue()) {  //第一次到达阈值，把前面符合条件的数据都存入警告集合；
                                abnormalDataIndexs.addAll(eightAbnormalIndex);
                            } else if (eightAbnormalIndex.size() > n.intValue()) {
                                abnormalDataIndexs.add(i);
                            }
                        }
                        // 不符合报警条件，归零重新计算
                        else {
                            eightAbnormalIndex.clear();
                        }
                        break;
                }

            }
        }
        abnormalDataIndexs = abnormalDataIndexs.stream().distinct().collect(Collectors.toList());
        Collections.sort(abnormalDataIndexs);
        return abnormalDataIndexs;
    }

    /**
     * 修改数据为异常
     */
    public void updateAbnormal(List<Map<String, Object>> data, List<Integer> integers) {
        for (Integer integer : integers) {
            Map<String, Object> map = data.get(integer);
            map.put("state", "失控");
        }
    }







    /*
    private void delCaches(Integer id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Integer> ids) {
        for (Integer id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<SpcMainDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (SpcMainDto spcMain : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("检测项目", spcMain.getTestItem());
              map.put("图类(0-x-R,1-x-s)", spcMain.getGraphType());
              map.put("产品型号", spcMain.getProductCode());
              map.put("产品名称", spcMain.getProductName());
              map.put("班组", spcMain.getTeamGroup());
              map.put("设备", spcMain.getEquipmentCode());
              map.put("工单编号", spcMain.getWorkOrderCode());
              map.put("规格上限", spcMain.getSpecificationUpperLimit());
              map.put("目标值", spcMain.getTargetValue());
              map.put("规格下限", spcMain.getSpecificationFloor());
              map.put("判断规则", spcMain.getJudgeRule());
              map.put("创建人", spcMain.getCreateBy());
              map.put("创建时间", spcMain.getCreateTime());
              map.put("更新人", spcMain.getUpdateBy());
              map.put("更新时间", spcMain.getUpdateTime());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/
}
